diff options
Diffstat (limited to 'src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt')
-rw-r--r-- | src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt new file mode 100644 index 000000000..7f9e2e2d4 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt @@ -0,0 +1,134 @@ +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.yuzu.yuzu_emu.adapters + +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.net.Uri +import android.text.TextUtils +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import androidx.documentfile.provider.DocumentFile +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.lifecycleScope +import androidx.preference.PreferenceManager +import androidx.recyclerview.widget.AsyncDifferConfig +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import coil.load +import kotlinx.coroutines.launch +import org.yuzu.yuzu_emu.NativeLibrary +import org.yuzu.yuzu_emu.R +import org.yuzu.yuzu_emu.YuzuApplication +import org.yuzu.yuzu_emu.databinding.CardGameBinding +import org.yuzu.yuzu_emu.activities.EmulationActivity +import org.yuzu.yuzu_emu.model.Game +import org.yuzu.yuzu_emu.adapters.GameAdapter.GameViewHolder +import org.yuzu.yuzu_emu.model.GamesViewModel + +class GameAdapter(private val activity: AppCompatActivity) : + ListAdapter<Game, GameViewHolder>(AsyncDifferConfig.Builder(DiffCallback()).build()), + View.OnClickListener { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GameViewHolder { + // Create a new view. + val binding = CardGameBinding.inflate(LayoutInflater.from(parent.context), parent, false) + binding.cardGame.setOnClickListener(this) + + // Use that view to create a ViewHolder. + return GameViewHolder(binding) + } + + override fun onBindViewHolder(holder: GameViewHolder, position: Int) { + holder.bind(currentList[position]) + } + + override fun getItemCount(): Int = currentList.size + + /** + * Launches the game that was clicked on. + * + * @param view The card representing the game the user wants to play. + */ + override fun onClick(view: View) { + val holder = view.tag as GameViewHolder + + val gameExists = DocumentFile.fromSingleUri(YuzuApplication.appContext, Uri.parse(holder.game.path))?.exists() == true + if (!gameExists) { + Toast.makeText( + YuzuApplication.appContext, + R.string.loader_error_file_not_found, + Toast.LENGTH_LONG + ).show() + + ViewModelProvider(activity)[GamesViewModel::class.java].reloadGames(true) + return + } + + val preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) + preferences.edit() + .putLong( + holder.game.keyLastPlayedTime, + System.currentTimeMillis() + ) + .apply() + + EmulationActivity.launch(activity, holder.game) + } + + inner class GameViewHolder(val binding: CardGameBinding) : + RecyclerView.ViewHolder(binding.root) { + lateinit var game: Game + + init { + binding.cardGame.tag = this + } + + fun bind(game: Game) { + this.game = game + + binding.imageGameScreen.scaleType = ImageView.ScaleType.CENTER_CROP + activity.lifecycleScope.launch { + val bitmap = decodeGameIcon(game.path) + binding.imageGameScreen.load(bitmap) { + error(R.drawable.default_icon) + } + } + + binding.textGameTitle.text = game.title.replace("[\\t\\n\\r]+".toRegex(), " ") + + binding.textGameTitle.postDelayed( + { + binding.textGameTitle.ellipsize = TextUtils.TruncateAt.MARQUEE + binding.textGameTitle.isSelected = true + }, + 3000 + ) + } + } + + private class DiffCallback : DiffUtil.ItemCallback<Game>() { + override fun areItemsTheSame(oldItem: Game, newItem: Game): Boolean { + return oldItem.gameId == newItem.gameId + } + + override fun areContentsTheSame(oldItem: Game, newItem: Game): Boolean { + return oldItem == newItem + } + } + + private fun decodeGameIcon(uri: String): Bitmap? { + val data = NativeLibrary.getIcon(uri) + return BitmapFactory.decodeByteArray( + data, + 0, + data.size, + BitmapFactory.Options() + ) + } +} |